define(['jquery','jquery_ext'], function($,jqext) {
	/**
	 * 路由属性对象 外部属性 带$ 全部回调方法上都可以取到
	 */
	window.$urlparams={};
	var Router = {
			$hashstr:'',//url 上面的hash值  (不可篡改) 
			$tplHtml:'',// 加载的html字符串 (不可篡改) 
			$tplData:{},//渲染html的数据 (可篡改) 
			$urlparams:{},//根据路由表和hash 提取的参数 (可篡改) //已注册到window
			$routerobj:{},//路由表的对象 (可篡改) 
			historyhash:[],//存放 历史记录
	};
	
	/**
	 * 路由配置信息内部属性
	 */
	var RouterConfig = {
			beforecallbackobj:function(){},//存放 前置回调方法
			callbackobj:function(){},//存放 回调方法
			unroutercallbackobj:function(){return true;},//存放 没有发现路由回调
			controllerobj:{},//存放控制器组
			htmlobj:{},//存放 html全局
			configobj:{}//存放路由配置
	};

	/**
	 * 路由controller方法定义
	 * **** 控制器定义  参数说明
	 * @param $name     控制器名字
	 * @param $function 控制器方法体
	 * 		$function 
	 * 		(		可选参数:
	 *  			$model:渲染 (方法) 用来调用callback,
	 *  			$render:渲染 (方法) 用来调用callback,
	 *  			$tplHtml:根据路由配置的获取的模板内容,
	 *  			$tplData:模板渲染对象,可从新定义 可数据传递给 callback,
	 *  			$urlparams:  Hash 参数值对象 根据hash 和 路由配置匹配得到的 参数对象,
	 *  			$routerobj:路由对象 根据hash 从路由配置得到的对象
	 * 		)
	 * 		
	 * ng:
	 * 
	 * $.controller("controllerName" ,  function( $render, $tplHtml ,$tplData, $urlparams , $routerobj){
	 * 		//此方法可根据需求调用 , 有ajax请求的数据时 需 放在异步回调方法内调用
	 * 		$render($tplData);
	 * });
	 * 
	 */
	Router.controller = function($name,$function){
		if(typeof $function === 'function'){
			RouterConfig.controllerobj[$name]=$function;
		}
		return this;
	};
	window.RouterController=RouterConfig.controllerobj;
	/** 
	 * 路配置由表信息
	 *  路由规则注册 eg:index.html#2/1
	 * 	定义hash事件 锚点定义规则#{id1}/{id2}
	 *  返回对象:返回键值对对象{id1:v1,id2:v2,...}
	 *  eg:
	 *  Router.config({
	 *  "index/{id}":{template:"goods/edit_goods.html",controller:'controller.indexzz',loadjs:'indexzz1'}
	 *  });
	 *  
	 *  Router.config(<object>);
	 *  1 注册路由规则  {"home":{
	 *												redirectTo:"string 重新定向内容 ng: home",
	 *  						        			openTo:"string 打开新页面定向内容 ng: home",
	 *  											templateUrl:"string ,模板地址 加载html内容   ng: demo.html ",
	 *  											template:"string 或 function(retobj) return string; ,模板地址内容 是html内容 如果和templateUrl 同时设置只会执行 templateUrl ng:<html>内容</html>",
	 *  											controller:"string  控制器 在所有控制器执行完成后执行控制器 ng: homeController",
	 *  											loadjs:"string 加载js文件"
	 *  									}
	 *  						}
	 *  
	 **/
	Router.config = function($config){
		if(typeof $config === 'object'){
			RouterConfig.configobj=$config;
		}
		if(typeof RouterConfig.startTime === 'undefined'){
			//只执行一次 设置启动时间
			RouterConfig.startTime=new Date().getTime();
			window.onhashchange = RouterConfig.routerHandler;
			$(document).ready(function(){
				var appv = window.navigator.appVersion;
				if (('onhashchange' in window) && appv.indexOf('MSIE 7') === -1 && appv.indexOf('MSIE 6') === -1){
					window.onhashchange();
				}else{
					// 版本兼容问题 
					var _tmphash = window.location.hash;
					window.setInterval(function() {
						var _curl = window.location.hash;
						if (_tmphash != _curl){
							_tmphash = _curl;
							if (window.onhashchange){
								window.onhashchange();
							}
						}
					}, 500);	
				}
			});
		}
		return this;
	};
	

	/**
	 * 路由前回调
	 */
	Router.beforecallback = function($beforecallback){
		if(typeof $beforecallback === 'function'){
			RouterConfig.beforecallbackobj=$beforecallback;
		}
		return this;
	};
	/**
	 * 回调
	 */
	Router.callback = function($callback){
		if(typeof $callback === 'function'){
			RouterConfig.callbackobj=$callback;
		}
		return this;
	};
	/**
	 * 没法路由回调
	 */
	Router.unroutercallback = function($unroutercallback){
		if(typeof $unroutercallback === 'function'){
			RouterConfig.unroutercallbackobj=$unroutercallback;
		}
		return this;
	};
	/**
	 * 加载html
	 */
	Router.loadhtml = function($url){
		var _html='';
		if(typeof RouterConfig.htmlobj[$url] === 'string'){
			_html = RouterConfig.htmlobj[$url];
		}else{
			// 请求加载html
			_html = $.loaddata($url);
	 		RouterConfig.htmlobj[$url] = _html;
		}
		return _html;
	};
	
	
	/**
	 * 路由处理方法
	 */
	RouterConfig.routerHandler = function(){
		var 
		_href,// url
		_findflag=false,//路由配置是否存在
		_dhref;//转义后的href 判断xss

		//初始化对象obj
		Router.$hashstr = location.hash.substring(1);//设置 hash 值 截取hash #
		//检测刷新标记
		var _resetExp = new RegExp('(.*?)@$');
		if(_resetExp.test(Router.$hashstr)){
			var _tmpHash=Router.$hashstr.match(_resetExp);
			if(_tmpHash.length==2){
				location.hash = '#'+_tmpHash[1];
				return;
			}
		}
		
		Router.$tplHtml = '';//模板内容
		Router.$tplData = {};//初始化模板对象
		Router.$urlparams = {};//URL 参数集合
		window.$urlparams = Router.$urlparams;//注册到window
		Router.$routerobj = {};//路由对象
		
		_href = location.href;
		_dhref = decodeURIComponent(_href);
		if(_dhref.indexOf('\'')!=-1||_dhref.indexOf('\"')!=-1||_dhref.indexOf('>')!=-1||_dhref.indexOf('<')!=-1){
			alert("URL地址存在非法字符 ( '  \"  >  < ) :  \r\n"+_href);
			return;
		}
		for(var routerurl in RouterConfig.configobj){
			// 转换/{id1}/{id2} 为/([^\/]*)/([^\/]*) 正则表达式   加上尾边界$
			var _urlpattern = '^'+routerurl.replace(/\{.*?\}/ig,'([^\/]*)')+'$';
			var _regExp = new RegExp(_urlpattern);
			//hash匹配，能匹配上，1:提取key 2:提取值 3:执行回调函数
			if(_regExp.test(Router.$hashstr)){
				_findflag=true;
				//添加到历史hash
				Router.historyhash.push('#'+Router.$hashstr);
				if(Router.historyhash.length>10){
					//如果历史超过10个那么删除第一个
					Router.historyhash.splice(0,1);
				}
				//1 提取key
				var _namekey = routerurl.replace(/{/g,'').replace(/}/g,'');
				var _keyarry = _namekey.match(_regExp);
				//2 提取值
				var _valuearray = Router.$hashstr.match(_regExp);
				// 设置通配符参数值
				for(var i=1;i<_valuearray.length;i++){
					var _tmpkey = Router.$urlparams[_keyarry[i]];
					if(typeof _tmpkey === 'undefined'){
						Router.$urlparams[_keyarry[i]] = _valuearray[i];
					}else{
						if(typeof _tmpkey === 'string'){
							Router.$urlparams[_keyarry[i]]=[];
							Router.$urlparams[_keyarry[i]].push(_tparam);
						}
						Router.$urlparams[_keyarry[i]].push(_valuearray[i]);
					}
				}
				//取路由配置的对象
				Router.$routerobj=RouterConfig.configobj[routerurl];
				if(typeof Router.$routerobj === 'object'){
					//执行路由操作
					
					// 1. 判断 跳转
					if(typeof Router.$routerobj.openTo === 'string'){
						// 打开新页面
						 window.open(Router.$routerobj.openTo);
					}else if(typeof Router.$routerobj.redirectTo === 'string'){
						// 重定向
						location.hash = '#' + Router.$routerobj.redirectTo;
					}else{
						
						//正常路由
						// 2.判断 取模板方法
						if(typeof Router.$routerobj.templateUrl === 'string'){
							Router.$tplHtml=Router.loadhtml(Router.$routerobj.templateUrl);
						}else if(typeof Router.$routerobj.template === 'string'){
							Router.$tplHtml=Router.$routerobj.template;
						}else if(typeof Router.$routerobj.template === 'function'){
							Router.$tplHtml=Router.$routerobj.template(Router.$urlparams);
						}
						
						//执行前置回调
						$.funParameterBind(RouterConfig.beforecallbackobj,{
							$hashstr:Router.$hashstr,
							$tplHtml:Router.$tplHtml,
							$tplData:Router.$tplData,
							$urlparams:Router.$urlparams,
							$routerobj:Router.$routerobj,
						});
						
						// 3. 判断 控制器
						if(typeof Router.$routerobj.controller === 'string'){
							//判断控制器是否存在
							RouterConfig.controllerHandler();
						}else{
							// 执行全局处理方法
							$.funParameterBind(RouterConfig.callbackobj,{
								$hashstr:Router.$hashstr,
								$tplHtml:Router.$tplHtml,
								$tplData:Router.$tplData,
								$urlparams:Router.$urlparams,
								$routerobj:Router.$routerobj
							});
						}
					}
				}//  if(typeof Router.$routerobj === 'object'){ end
				return;
			}// if(_regExp.test(Router.$hashstr)){  end
		}// for end
		//没找到路由时候调用
		if(!_findflag){
			if(RouterConfig.unroutercallbackobj(Router.$hashstr) && Router.historyhash.length > 0){
				window.location.hash = Router.historyhash.pop();
			}
		}
	};
	
	/**
	 * 控制器处理方法
	 */
	RouterConfig.controllerHandler = function($executed){
		//控制器是否存在判断
		if(typeof RouterConfig.controllerobj[Router.$routerobj.controller] === 'function'){
			var _render=function($tplData){
				// 后面交给全局处理方法
				if(typeof $tplData == 'object'){
					Router.$tplData=$tplData;
				}
				// 执行全局处理方法
				$.funParameterBind(RouterConfig.callbackobj,{
					$hashstr:Router.$hashstr,
					$tplHtml:Router.$tplHtml,
					$tplData:Router.$tplData,
					$urlparams:Router.$urlparams,
					$routerobj:Router.$routerobj
				});
			};
			//执行控制器
			$.funParameterBind(RouterConfig.controllerobj[Router.$routerobj.controller],{
					$model:_render,//做兼容
					$render:_render,
					$hashstr:Router.$hashstr,
					$tplHtml:Router.$tplHtml,
					$tplData:Router.$tplData,
					$defobj:Router.$tplData,//做兼容
					$urlparams:Router.$urlparams,
					$paramobj:Router.$urlparams,//做兼容
					$modelobj:Router.$routerobj,//做兼容
					$routerobj:Router.$routerobj
			});
		}else if(typeof $executed === 'undefined'){
			//加载控制器
			if(typeof Router.$routerobj.loadjs === 'string'){
				require([Router.$routerobj.loadjs], function (){
					RouterConfig.controllerHandler('exec');
				});
			}else if(Router.$routerobj.controller.indexOf('controller.') === 0){
				var _controlerjs=Router.$routerobj.controller.substring(11);
				require(['../js/modules/'+_controlerjs.replace('\.','/')+'.js'], function (){
					RouterConfig.controllerHandler('exec');
				});
			}else if(Router.$routerobj.controller != 'mainController' && Router.$routerobj.controller != 'default'){
				require([Router.$routerobj.controller], function (){
					RouterConfig.controllerHandler('exec');
				});
			}
		}
	};

	$.extend({ controller : Router.controller});
	$.fn.extend({ controller:Router.controller});
	
	$.extend({ setHTML : Router.loadhtml});
	$.fn.extend({ setHTML:Router.loadhtml});
	
	return Router;
});